import java.util.Iterator;
import java.util.HashMap;
import java.util.TreeSet;

public class RovingEye {

	double[][][] data;
	NeuralNet net;
	
	public RovingEye() {
		data = training();
		String[][] layout = {{"B", "L", "L", "L", "L", "L", "L", "L", "L", "L"},
									{"SC", "SC", "SC", "SC", "SC", "SC", "SC", "SC", "SC"}};
		net = new NeuralNet(NeuralNet.quickCPPN(layout), 0);
	}
	
	public static void main(String[] args) {
		RovingEye eye = new RovingEye();
		double e = Double.POSITIVE_INFINITY;
		while (e > 1.0) {
			e = eye.net.trainNetwork(eye.data, 0.1);
			System.out.println(e);
		}
		eye.evaluate();
	}
	
	public double[][][] training() {
		double[][][] r = new double[35][3][9];
        for (int i = 0; i < 25; i++) {
            double[][] t = new double[7][7];
            for (int j = 0; j < 9; j++) {
                t[i/5 + j/3][i%5 + j%3] = 1;
            }
            for (int j = 0; j < 9; j++) {
                r[i][0][j] = t[2 + j/3][2 + j%3];
                if (i == 12 && j == 4) {
                    r[i][1][j] = 1;
                }
                r[i][2][j] = j;
            }
        }
        for (int i = 0; i < 9; i++) {
            r[25+i][0][i] = 1;
            //no output
            for (int j = 0; j < 9; j++) {
                r[25+i][2][j] = j;
            }
        }
        //no input and output
        for (int j = 0; j < 9; j++) {
                r[34][2][j] = j;
        }
        return r;
	}
	
	public TestData[] data() {
		TestData[] r = new TestData[9072];
		int k = 0;
		for (int i = 1; i < 10; i++) {
			for (int j = 1; j < 10; j++) {
				for (int n = 0; n < 11; n++) {
					for (int m = 0; m < 11; m++) {
						//Input
						boolean f = true;
						for (int a = -1; a < 2; a++) {
							for (int b = -1; b < 2; b++) {
								if (i+a == n && j+b == m) {
									f = false;
								}
							}
						}
						if (f) {
							r[k] = new TestData(i-1,j-1,n,m);
							k++;
							if (k > 9071) {
								return r;
							}
						}
					}
				}
			}
		}
		return r;
	}
	
	public void evaluate() {
    	TestData[] test = data();
        HashMap<Double, Integer> store = new HashMap<Double, Integer>();
    	for (int i = 0; i < test.length; i++) {
    		double[][] frames = test[i].fr;
            int[] c = new int[2];
            double m = Double.NEGATIVE_INFINITY;
    		for (int j = 0; j < frames.length; j++) {
    			net.processInput(frames[j]);
                double[] v = net.getOutputs();
                for (int k = 0; k < v.length; k++) {
                    if (v[k] > m) {
                        m = v[k];
                        c[0] = j/9 + k/3;
                        c[1] = j%9 + k%3;
                    }
                }
    		}
            double d = Math.sqrt(Math.pow(test[i].cc[0]-c[0],2) + Math.pow(test[i].cc[1]-c[1],2));
            if (store.containsKey(d)) {
				int count = store.get(d);
				store.put(d, count+1);
			} else {
				store.put(d, 1);
			}
    	}
        TreeSet<Double> k = new TreeSet<Double>();
		k.addAll(store.keySet());
		Iterator<Double> iter = k.iterator();
		while(iter.hasNext()) {
			double v = iter.next();
			System.out.println(v+": "+store.get(v));
		}
    }
    
    private class TestData {
        
        double[][] im = new double[11][11];
        double[][] fr = new double[81][9];
        double[] cc = new double[2];
        
        public TestData(int bx, int by, int sx, int sy) {
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    im[bx+i][by+j] = 1;
                }
            }
            im[sx][sy] = 1;
            
			for (int i = 0; i < 9; i++) {
                for (int j = 0; j < 9; j++) {
                    for (int k = 0; k < 9; k++) {
                        fr[i*9+j][k] = im[i+k/3][j+k%3];
                    }
				}
			}
            
            cc[0] = bx+1;
            cc[1] = by+1;
        }
    }
}
